package com.onluy.frameworkcloud.data.entity;


import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.onluy.frameworkcloud.data.annotation.Column;

public abstract class EntityHelper
{
    private static final Logger log = LoggerFactory.getLogger(EntityHelper.class);

    public static Class<? extends BaseEntity> getEntityClazz(Entity entity)
    {
        if ((entity instanceof Conditions))
            return ((Conditions)entity).getEntityClazz();
        if (entity.getClass().isAnonymousClass()) {
            return (Class<? extends BaseEntity>) entity.getClass().getSuperclass();
        }
        return ((BaseEntity)entity).getClass();
    }

    public static Map<String, OperColumn> operColumns(Entity entity) {
        return ((AbstractEntity)entity).operColumns();
    }

    public static Map<String, Field> getAllColumnFields(Class<?> clazz)
    {
        Map allFields = new HashMap();
        List clazzs = new ArrayList();

        for (; clazz != BaseEntity.class; clazz = clazz.getSuperclass()) {
            clazzs.add(clazz);
        }

        Collections.reverse(clazzs);

        for (Object clztemp : clazzs) {
            Class  clz=(Class)clztemp;
            Field[] fields = clz.getDeclaredFields();
            for (Field field : fields) {
                Column columnAnn = (Column)field.getAnnotation(Column.class);
                if (columnAnn != null) {
                    allFields.put(columnAnn.name(), field);
                }
            }
        }
        return allFields;
    }

    public static <T> T map2entity(Map src, Class<? extends BaseEntity> targetClazz)
    {
        Object target = null;
        Class currentClazz = targetClazz;
        try {
            target = targetClazz.newInstance();
            if ((src != null) && (!src.isEmpty())) {
                List clazzs = new ArrayList();

                for (; currentClazz != BaseEntity.class; currentClazz = currentClazz.getSuperclass()) {
                    clazzs.add(currentClazz);
                }

                Collections.reverse(clazzs);

                    for (Object clztemp : clazzs) {
                        Class  clz=(Class)clztemp;
                    Field[] fields = clz.getDeclaredFields();
                    for (Field field : fields) {
                        Column columnAnn = (Column)field.getAnnotation(Column.class);
                        if (columnAnn != null) {
                            String columnName = columnAnn.name();
                            if (src.containsKey(columnName)) {
                                Object value = src.get(columnName);
                                String methodName = "set" + toUpperCaseFirstOne(field.getName());
                                targetClazz.getMethod(methodName, new Class[] { field.getType() }).invoke(target, new Object[] { value });
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return (T) target;
    }

    public static <T> T entity2map(BaseEntity src, Class<? extends Map> targetClazz)
    {
        return entity2map(src, targetClazz, false);
    }

    public static <T> T entity2map(BaseEntity src, Class<? extends Map> targetClazz, boolean keyIsColumn)
    {
        Map target = null;
        Class currentClazz = src.getClass();
        try {
            target = (Map)targetClazz.newInstance();
            if ((src != null) && (src.operColumns() != null) && (!src.operColumns().isEmpty())) {
                List clazzs = new ArrayList();

                for (; currentClazz != BaseEntity.class; currentClazz = currentClazz.getSuperclass()) {
                    clazzs.add(currentClazz);
                }

                Collections.reverse(clazzs);

                for (Object clztemp : clazzs) {
                    Class  clz=(Class)clztemp;
                    Field[] fields = clz.getDeclaredFields();
                    for (Field field : fields) {
                        Column columnAnn = (Column)field.getAnnotation(Column.class);
                        if (columnAnn != null) {
                            String methodName = "get" + toUpperCaseFirstOne(field.getName());
                            String key = field.getName();
                            if (keyIsColumn) {
                                key = columnAnn.name();
                            }
                            target.put(key, src.getClass().getMethod(methodName, new Class[0]).invoke(src, new Object[0]));
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return (T) target;
    }

    private static String toUpperCaseFirstOne(String s) {
        if (Character.isUpperCase(s.charAt(0))) {
            return s;
        }
        return Character.toUpperCase(s.charAt(0)) + s.substring(1);
    }

    public String getUniqeName() {
        return String.valueOf(System.currentTimeMillis()) + Math.abs(new Random().nextInt());
    }
}